classdef DO < Processor
  % Class for calculating dissolved oxygen ala SBE Derive
  % Derived from Processor
  % Constructor signature: do = DO(data, conn, T, P, V, OS, windowSize), 
  %     all args. optional
  %
  % Author: David Goldsmith, Wash. State Dept. of Ecology, dgol461@ecy.wa.gov
  % Release date: N/A
  
    properties
      % inherited from Processor
      % inData;
      % castDT;
      % scanRate;
      % ParamID;
      % ParamDesc;
      % SBEprec;
      % EquipID;
        DBdata;
        outData;
        dateValid;
        calibCoeffs;
    end
    
    methods
        function do = DO(data, conn, T, P, V, OS) % Constructor
            do = do@Processor(data);
            if nargin
                do.calibCoeffs = data.Sensors.OxygenSensor;
            end

            if nargin > 1, do.getDBdata(conn, 'O'); end
            if nargin==6, do.mainFormula(T, P, V, OS); end
        end
        
        function delete(obj) % Destructor
            % Here in case I need it
        end
        
        function mainFormula(obj, T, P, V, OS)
          % T = temperature deg C ITS-90, P = pressure db
          % V = hysteresis-corrected (if applicable) dissolved oxygen sensor voltage
          % OS = Garcia-Gordon Ox Sat Conc., mL/L
            global instHeaderData mSB

            if obj.calibCoeffs.equation
                scanRate = instHeaderData.scanRate;
                Soc = obj.calibCoeffs.Soc;
                Voffset = obj.calibCoeffs.offset;
                A = obj.calibCoeffs.A;
                B = obj.calibCoeffs.B;
                C = obj.calibCoeffs.C;
                E = obj.calibCoeffs.E;
                if mSB
                    T = round2(T, 1e-4);
                    P = round2(P, 1e-3);
                    V = round2(V, 1e-4);
                end
                if obj.DBdata.OApplyTauCorrection
                  % Implementation, incl. derivative calc., verified 4/12/2012
                    D = [obj.calibCoeffs.D1; obj.calibCoeffs.D2];
                    t20 = obj.calibCoeffs.Tau20;
                    tau = t20 * exp([P (T-20)] * D);
                    dVdt = zeros(size(V));
                    t = (0:(1/instHeaderData.scanRate):obj.DBdata.OwindowSize)';
                    a = [t ones(size(t))];
                    window = numel(t);
                    for n = (floor(window/2)+1) : (numel(dVdt)-floor(window/2))
                        mb = a\V(n-floor(window/2) : n+floor(window/2));
                        dVdt(n) = mb(1);
                    end
                else
                    tau = 0; dVdt = 0;
                end
              % With all intermediate post-processing (i.e., Filter, Align CTD,
              % CTM conductivity correction, and Loop Edit), as well as the
              % hysteresis and tau corrections turned off, the below produces 
              % DO results matching those of SBE Data Processing Version 7.20b's
              % Derive module to better than 5e-4.  This level of precision is
              % better than SeaBird's stated accuracy (1e-3) for the instrument
              % in question, i.e., it is below the instrument's "advertised" 
              % detection limit.  Accordingly, the implementation has been
              % deemed "close enough."
                obj.outData = Soc * (V + Voffset + tau .* dVdt) .* ...
                              OS .* (1 + T.*(A + T.*(B + C*T))) .* ...
                              exp(E * P ./ (T + 273.15));
            else
                obj.outData = 'Formula not yet implemented';
            end
        end
        
    end
    
end